#!/usr/bin/env python
# encoding: utf-8
'''
@author: wangjianrong
@software: pycharm
@file: 协程.py
@time: 2020/10/12 11:30
@desc:
https://www.jianshu.com/p/50384d0d3940
'''

import time


import time
import asyncio

# def consumer():
#     status = True
#     while True:
#         n = yield status
#         print("我拿到了{}!".format(n))
#         if n == 3:
#             status = False
#
#
# def producer(consumer):
#     n = 5
#     while n > 0:
#     # yield给主程序返回消费者的状态
#         yield consumer.send(n)
#         n -= 1
# if __name__ == '__main__':
#     c = consumer()
#     # c.send(None)
#     c.__next__()
#     p = producer(c)
#     for status in p:
#         if status == False:
#             print("我只要3,4,5就行啦")
#             break
#     print("程序结束")




# def consumer():
#     r = ''
#     while True:
#         n = yield r  # 执行的中断点
#         if not n:
#             return
#         print('[消费者] 正在消费:{0}'.format(n))
#         r = '200 人民币'
#
#
# def produce(c):
#     t = c.send(None)  # 启动消费者（生成器）——实际上是函数调用，只不过生成器不是直接象函数那般调用的
#     n = 0
#     while n < 5:
#         n = n + 1
#         print('[生产者] 正在生产:{0}'.format(n))
#         r = c.send(n)  # 给消费者传入值——实际上也是函数调用
#         print('[生产者] 消费者返回:{0}'.format(r))
#         print('-------------------------------------------------')
#     c.close()
#
#
# c = consumer()  # 构造一个生成器
# produce(c)




# # 定义一个消费者，他有名字name
# # 因为里面有yield，本质上是一个生成器
# def consumer(name):
#     print(f'{name}  准备吃包子啦！,呼吁店小二')
#     while True:
#         baozi = yield  # 接收send传的值，并将值赋值给变量baozi
#         print(f'包子 {baozi + 1} 来了,被 {name} 吃了！')
#
#
# # 定义一个生产者，生产包子的店家，店家有一个名字name,并且有两个顾客c1 c2
# def producer(name, c1, c2):
#     t1 = next(c1)  # 启动生成器c1
#     t2 = next(c2)  # 启动生成器c2
#     print(f'{name} 开始准备做包子啦！')
#     for i in range(5):
#         time.sleep(1)
#         print(f'做了第{i + 1}包子，分成两半,你们一人一半')
#         c1.send(i)
#         c2.send(i)
#         print('------------------------------------')
#
#
# c1 = consumer('张三')  # 把函数变成一个生成器
# c2 = consumer('李四')
# producer('店小二',c1,c2)


# def average():
# #     total = 0.0  # 数字的总和
# #     count = 0  # 数字的个数
# #     avg = None  # 平均值
# #     while True:
# #         num = yield avg
# #         total += num
# #         count += 1
# #         avg = total / count
# #
# #
# # # 定义一个函数，通过这个函数向average函数发送数值
# # def sender(generator):
# #     print(next(generator))  # 启动生成器
# #     print(generator.send(10))  # 10
# #     print(generator.send(20))  # 15
# #     print(generator.send(30))  # 20
# #     print(generator.send(40))  # 25
# #
# #
# # g = average()
# # sender(g)


from inspect import getgeneratorstate  # 一定要导入
from time import sleep


# def my_generator():
#     for i in range(3):
#         sleep(0.5)
#         x = yield i + 1
#
#
# g = my_generator()  # 创建一个生成器对象
#
#
# def main(generator):
#     try:
#         print("生成器初始状态为:{0}".format(getgeneratorstate(generator)))
#         next(generator)  # 激活生成器
#         print("生成器初始状态为:{0}".format(getgeneratorstate(generator)))
#         generator.send(100)
#         print("生成器初始状态为:{0}".format(getgeneratorstate(generator)))
#         next(generator)
#         print("生成器初始状态为:{0}".format(getgeneratorstate(generator)))
#         next(generator)
#     except StopIteration:
#         print('全部迭代完毕了')
#         print("生成器初始状态为:{0}".format(getgeneratorstate(generator)))
#
#
# main(g)

# import time
# import asyncio
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:", x)
#
# start = now()
# # 这里是一个协程对象，这个时候do_some_work函数并没有执行
# coroutine = do_some_work(2)
# print(coroutine)
# #  创建一个事件loop
# loop = asyncio.get_event_loop()
# # 将协程加入到事件循环loop
# loop.run_until_complete(coroutine)
#
# print("Time:",now()-start)


# import asyncio
# import time
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:", x)
#
# start = now()
#
# coroutine = do_some_work(2)
# loop = asyncio.get_event_loop()
# task = loop.create_task(coroutine)
# print(task)
# loop.run_until_complete(task)
# print(task)
# print("Time:",now()-start)

# import time
# import asyncio
#
# now = lambda : time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     return "Done after {}s".format(x)
#
# def callback(future):
#     print("callback:",future.result())
#
# start = now()
# coroutine = do_some_work(2)
# loop = asyncio.get_event_loop()
# task = asyncio.ensure_future(coroutine)
# print(task)
# task.add_done_callback(callback)
# print(task)
# loop.run_until_complete(task)
#
# print("Time:", now()-start)


# import asyncio
# import time
#
# now = lambda :time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     # await 后面就是调用耗时的操作
#     await asyncio.sleep(x)
#     return "Done after {}s".format(x)
#
# start = now()
#
# coroutine = do_some_work(2)
# loop = asyncio.get_event_loop()
# task = asyncio.ensure_future(coroutine)
# loop.run_until_complete(task)
#
# print("Task ret:", task.result())
# print("Time:", now() - start)


# import asyncio
# import time
#
# now = lambda :time.time()
#
# def mysleep(t):
#     sleep(t)
#     return t*t
#
#
# async def do_some_work(x):
#     print("Waiting:",x)
#     t = await asyncio.sleep(x)
#     print(t)
#     return "Done after {}s".format(x)
#
# start = now()
#
# coroutine1 = do_some_work(1)
# coroutine2 = do_some_work(2)
# coroutine3 = do_some_work(4)
#
# tasks = [
#     asyncio.ensure_future(coroutine1),
#     asyncio.ensure_future(coroutine2),
#     asyncio.ensure_future(coroutine3)
# ]
#
# loop = asyncio.get_event_loop()
# loop.run_until_complete(asyncio.wait(tasks))
#
# for task in tasks:
#     print("Task ret:",task.result())
#
# print("Time:",now()-start)


# import asyncio
# import time
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     await asyncio.sleep(x)
#     return "Done after {}s".format(x)
#
# async def main():
#     coroutine1 = do_some_work(1)
#     coroutine2 = do_some_work(2)
#     coroutine3 = do_some_work(4)
#     tasks = [
#         asyncio.ensure_future(coroutine1),
#         asyncio.ensure_future(coroutine2),
#         asyncio.ensure_future(coroutine3)
#     ]
#
#     dones, pendings = await asyncio.wait(tasks)
#     for task in dones:
#         print("Task ret:", task.result())
#
#     # results = await asyncio.gather(*tasks)
#     # for result in results:
#     #     print("Task ret:",result)
#
#
# start = now()
#
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# print("Time:", now()-start)


# import asyncio
# import time
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     await asyncio.sleep(x)
#     return "Done after {}s".format(x)
#
# async def main():
#     coroutine1 = do_some_work(1)
#     coroutine2 = do_some_work(2)
#     coroutine3 = do_some_work(4)
#     tasks = [
#         asyncio.ensure_future(coroutine1),
#         asyncio.ensure_future(coroutine2),
#         asyncio.ensure_future(coroutine3)
#     ]
#     return await asyncio.gather(*tasks)
#
# start = now()
#
# loop = asyncio.get_event_loop()
# results = loop.run_until_complete(main())
# for result in results:
#     print("Task ret:",result)
#
# print("Time:", now()-start)

# import asyncio
# import time
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     await asyncio.sleep(x)
#     return "Done after {}s".format(x)
#
# async def main():
#     coroutine1 = do_some_work(1)
#     coroutine2 = do_some_work(2)
#     coroutine3 = do_some_work(4)
#     tasks = [
#         asyncio.ensure_future(coroutine1),
#         asyncio.ensure_future(coroutine2),
#         asyncio.ensure_future(coroutine3)
#     ]
#     return await asyncio.wait(tasks)
#
# start = now()
#
# loop = asyncio.get_event_loop()
# done,pending = loop.run_until_complete(main())
# for task in done:
#     print("Task ret:",task.result())
#
# print("Time:", now()-start)

# import asyncio
# import time
#
# now = lambda: time.time()
#
# async def do_some_work(x):
#     print("waiting:",x)
#     await asyncio.sleep(x)
#     return "Done after {}s".format(x)
#
# async def main():
#     coroutine1 = do_some_work(1)
#     coroutine2 = do_some_work(2)
#     coroutine3 = do_some_work(4)
#     tasks = [
#         asyncio.ensure_future(coroutine1),
#         asyncio.ensure_future(coroutine2),
#         asyncio.ensure_future(coroutine3)
#     ]
#     for task in asyncio.as_completed(tasks):
#         result = await task
#         print("Task ret: {}".format(result))
#
# start = now()
#
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# print("Time:", now()-start)


# import asyncio
# from threading import Thread
# import time
#
# now = lambda :time.time()
#
# def start_loop(loop):
#     asyncio.set_event_loop(loop)
#     loop.run_forever()
#
# def more_work(x):
#     print('More work {}'.format(x))
#     time.sleep(x)
#     print('Finished more work {}'.format(x))
#
# start = now()
# new_loop = asyncio.new_event_loop()
# t = Thread(target=start_loop, args=(new_loop,))
# t.start()
# print('TIME: {}'.format(time.time() - start))
#
# new_loop.call_soon_threadsafe(more_work, 6)
# new_loop.call_soon_threadsafe(more_work, 3)

# import asyncio
# import time
# from threading import Thread
#
# now = lambda :time.time()
#
# def start_loop(loop):
#     asyncio.set_event_loop(loop)
#     loop.run_forever()
#
# async def do_some_work(x):
#     print('Waiting {}'.format(x))
#     await asyncio.sleep(x)
#     print('Done after {}s'.format(x))
#
# def more_work(x):
#     print('More work {}'.format(x))
#     time.sleep(x)
#     print('Finished more work {}'.format(x))
#
# start = now()
# new_loop = asyncio.new_event_loop()
# t = Thread(target=start_loop, args=(new_loop,))
# t.start()
# print('TIME: {}'.format(time.time() - start))
#
# asyncio.run_coroutine_threadsafe(do_some_work(6), new_loop)
# asyncio.run_coroutine_threadsafe(do_some_work(4), new_loop)


import asyncio
import time
import random

now = lambda: time.time()


s = now()

async def first(x):
    await asyncio.sleep(random.random())
    return x

async def second(x):
    await asyncio.sleep(random.random())
    return x**2

async def third(x):
    await asyncio.sleep(random.random())
    return x**3

async def cal(x):
    res1 = await first(x)
    res2 = await second(res1)
    res3 = await third(res2)
    return res1 + res2 + res3

#直接在函数中解析结果
def do_smoke_work():
    # c1 = cal(1)
    # c2 = cal(2)
    # c3 = cal(3)
    # tasks = [
    #     asyncio.ensure_future(c1),
    #     asyncio.ensure_future(c2),
    #     asyncio.ensure_future(c3)
    # ]

    s = now()
    tasks = []
    for i in range(1, 10):
        tasks.append(asyncio.ensure_future(cal(i)))
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*tasks))
    for result in results:
        print(result)
    # dones,pendings = loop.run_until_complete(asyncio.wait(tasks))
    # for result in dones:
    #     print(result.result())
    print(now()-s)

do_smoke_work()

#返回结果，在函数外解析
async def do_smoke_work2():
    # c1 = cal(1)
    # c2 = cal(2)
    # c3 = cal(3)
    # tasks = [
    #     asyncio.ensure_future(c1),
    #     asyncio.ensure_future(c2),
    #     asyncio.ensure_future(c3)
    # ]
    tasks = []
    for i in range(1,10):
        tasks.append(asyncio.ensure_future(cal(i)))
    return await asyncio.gather(*tasks)
    # return await asyncio.wait(tasks)

s = now()

loop = asyncio.get_event_loop()
results = loop.run_until_complete(do_smoke_work2())
for result in results:
    print(result)
#
# dones,pendings = loop.run_until_complete(do_smoke_work2())
# for result in dones:
#     print(result.result())

print(now()-s)


